package com.yowasa.xiuxian.service.helper;

import cn.hutool.core.lang.WeightRandom;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.yowasa.xiuxian.engine.CommonEngine;
import com.yowasa.xiuxian.engine.item.ItemInterface;
import com.yowasa.xiuxian.entity.bo.item.ItemAttr;
import com.yowasa.xiuxian.entity.bo.item.UserItemBo;
import com.yowasa.xiuxian.entity.bo.user.UserBO;
import com.yowasa.xiuxian.entity.enums.ItemTypeEnum;
import com.yowasa.xiuxian.entity.enums.QualityEnum;
import com.yowasa.xiuxian.entity.po.*;
import com.yowasa.xiuxian.exception.HandlerException;
import com.yowasa.xiuxian.mapper.XiuxianDrawingMapper;
import com.yowasa.xiuxian.mapper.XiuxianShopItemMapper;
import com.yowasa.xiuxian.mapper.XiuxianUserEquipMapper;
import com.yowasa.xiuxian.mapper.XiuxianUserItemMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class ItemHelper {
    @Autowired
    private XiuxianUserItemMapper xiuxianUserItemMapper;

    @Autowired
    private XiuxianUserEquipMapper xiuxianUserEquipMapper;

    @Autowired
    private XiuxianDrawingMapper xiuxianDrawingMapper;

    @Autowired
    private XiuxianShopItemMapper xiuxianShopItemMapper;

    public List<UserItemBo> list(Long accountId,Integer size,String type) {

        LambdaQueryWrapper<XiuxianUserItemPO> wrapper = new LambdaQueryWrapper<XiuxianUserItemPO>()
                .eq(XiuxianUserItemPO::getAccountId, accountId)
                .ge(XiuxianUserItemPO::getItemNum, 1);
        ItemTypeEnum byName = ItemTypeEnum.getByName(type);
        if(ObjectUtil.isNotNull(byName)){
            wrapper.eq(XiuxianUserItemPO::getItemType,byName.getId());
        }
        Page<XiuxianUserItemPO> page = new Page<>(size,25);

        Page<XiuxianUserItemPO> xiuxianUserItemPOPage = xiuxianUserItemMapper.selectPage(page, wrapper);
        List<XiuxianUserItemPO> records = xiuxianUserItemPOPage.getRecords();
        return records.stream().map(UserItemBo::buildByPo).collect(Collectors.toList());


    }

    public UserItemBo getMyItem(Long accountId, String itemName) {
        XiuxianUserItemPO xiuxianUserItem = xiuxianUserItemMapper.selectOne(new LambdaQueryWrapper<XiuxianUserItemPO>()
                .eq(XiuxianUserItemPO::getAccountId, accountId)
                .ge(XiuxianUserItemPO::getItemNum, 1)
                .eq(XiuxianUserItemPO::getItemName, itemName).last("limit 1 for update")
        );
        if (xiuxianUserItem == null) {
            return null;
        }
        // 业务对象和数据库对象区分这么严格？bo里有多个po才要这样玩吧，这不脱裤子放屁吗
        return UserItemBo.buildByPo(xiuxianUserItem);
    }

    public UserItemBo getMyItemForAdd(Long accountId, String itemName) {
        XiuxianUserItemPO xiuxianUserItem = xiuxianUserItemMapper.selectOne(new LambdaQueryWrapper<XiuxianUserItemPO>()
                .eq(XiuxianUserItemPO::getAccountId, accountId)
                .eq(XiuxianUserItemPO::getItemName, itemName)
        );
        if (xiuxianUserItem == null) {
            return null;
        }
        return UserItemBo.buildByPo(xiuxianUserItem);
    }

    public void dropItem(UserItemBo myItem, int i) {
        myItem.setItemNum(myItem.getItemNum() - i);
        xiuxianUserItemMapper.updateById(myItem);
    }

    public void addItem(UserBO user, ItemInterface itemInterface, int num) {
        add(user, itemInterface, num);
    }

    private void add(UserBO user, ItemInterface itemInterface, int num) {

        UserItemBo myItem = getMyItemForAdd(user.getId(), itemInterface.getName());
        if (myItem != null) {
            myItem.setItemNum(myItem.getItemNum() + num);
            xiuxianUserItemMapper.updateById(myItem);
        } else {
            UserItemBo item = new UserItemBo();
            item.setItemNum(num);
            item.setItemName(itemInterface.getName());
            item.setAccountId(user.getId());
            item.setItemAttr(itemInterface.attr(QualityEnum.LIANG));
            item.setItemDesc(itemInterface.desc());
            item.setItemType(itemInterface.getType().getId());
            item.setItemPrice(itemInterface.getPrice());
            xiuxianUserItemMapper.insert(item);
        }
    }

    //向背包中增加装备
    public void addEquip(UserBO user, ItemInterface itemInterface, int num,int quality){
        UserItemBo myItem = getMyItemForAddEquip(user.getId(), itemInterface.getName(),quality);
        if (myItem != null) {
            myItem.setItemNum(myItem.getItemNum() + num);
            xiuxianUserItemMapper.updateById(myItem);
        } else {
            UserItemBo item = new UserItemBo();
            item.setItemNum(num);
            item.setItemName(itemInterface.getName());
            item.setAccountId(user.getId());
            QualityEnum byId = QualityEnum.getById(quality);
            item.setItemAttr(itemInterface.attr(byId));
            item.setItemDesc(itemInterface.desc());
            item.setItemType(itemInterface.getType().getId());
            item.setItemPrice(itemInterface.getPrice());
            xiuxianUserItemMapper.insert(item);
        }
    }


    private UserItemBo getMyItemForAddEquip(Long id, String name, int quality) {
        List<XiuxianUserItemPO> xiuxianUserItem = xiuxianUserItemMapper.selectList(new LambdaQueryWrapper<XiuxianUserItemPO>()
                .eq(XiuxianUserItemPO::getAccountId, id)
                .eq(XiuxianUserItemPO::getItemName, name)
        );
        if (xiuxianUserItem.size() == 0) {
            return null;
        }
        for (XiuxianUserItemPO item : xiuxianUserItem){
            if(quality == JSONUtil.toBean(item.getItemAttr(), ItemAttr.class).getQuality()){
                return UserItemBo.buildByPo(item);
            }
        }
        return null;

    }

    public void addItem(UserBO user, String itemName, int num) {
        ItemInterface itemInterface = CommonEngine.ITEM_MAP.get(itemName);
        add(user, itemInterface, num);
    }

    //野外掉落用，所以野外不给掉装备！
    public void addItems(UserBO userBO, Map<String, Integer> itemGet) {
        for (Map.Entry<String, Integer> entry : itemGet.entrySet()) {
            ItemInterface itemInterface = CommonEngine.ITEM_MAP.get(entry.getKey());
            addItem(userBO, itemInterface, entry.getValue());
        }
    }

    public String buildTransactMsgT(XiuxianTransactPO po) {
        //武器【xxx】*100，
        return MessageFormat.format("{0}[{1}]*{2},总价{3}", ItemTypeEnum.getById(po.getItemType()).getName(), po.getItemName(), po.getItemNum(), po.getItemPrice());
    }
    public String buildBatchTransactMsgT(List<XiuxianTransactPO> po) {
        return po.stream().map(this::buildTransactMsgT).collect(Collectors.joining("\n"));
    }

    public String buildTransactMsg(XiuxianShopItem po) {
        //武器【xxx】*100，单价100
        return MessageFormat.format("{0}[{1}]*{2},单价{3}", ItemTypeEnum.getById(po.getItemType()).getName(), po.getItemName(), po.getItemNum(), po.getPrice());
    }
    public String buildBatchTransactMsg(List<XiuxianShopItem> po) {
        return po.stream().map(this::buildTransactMsg).collect(Collectors.joining("\n"));
    }

    //穿上装备
    public void useEquip(UserItemBo myItem,Integer quality) {
        XiuxianUserEquip equip = new XiuxianUserEquip();
        equip.setAccountId(myItem.getAccountId());
        equip.setItemName(myItem.getItemName());
        equip.setItemAttr(myItem.getItemAttr());
        equip.setQuality(quality);
        xiuxianUserEquipMapper.insert(equip);
    }

    //查询身上所有穿戴的装备
    public List<XiuxianUserEquip> listEqip(Long id) {
        List<XiuxianUserEquip> xiuxianUserEquips = xiuxianUserEquipMapper.selectList(new LambdaQueryWrapper<XiuxianUserEquip>()
                .eq(XiuxianUserEquip::getAccountId,id));
        return xiuxianUserEquips;
    }

    //校验身上穿戴的装备数量
    public Long checkEqipNum(UserBO user) {
        return xiuxianUserEquipMapper.selectCount(new LambdaQueryWrapper<XiuxianUserEquip>().eq(XiuxianUserEquip::getAccountId,user.getId()));
    }

    //按品质和名称查找背包中的装备
    public UserItemBo getMyEqip(Long id, String itemName, Integer quality) {
        List<XiuxianUserItemPO> xiuxianUserItemPOS = xiuxianUserItemMapper.selectList(new LambdaQueryWrapper<XiuxianUserItemPO>()
                .eq(XiuxianUserItemPO::getAccountId, id)
                .ge(XiuxianUserItemPO::getItemNum, 1)
                .eq(XiuxianUserItemPO::getItemName, itemName).last("for update")
        );
        if (xiuxianUserItemPOS.size() == 0) {
            return null;
        }
        XiuxianUserItemPO xiuxianUserItemPO = xiuxianUserItemPOS.stream().filter(i -> JSONUtil.toBean(i.getItemAttr(), ItemAttr.class).getQuality() == quality).findFirst().orElse(null);
        if(xiuxianUserItemPO == null){
            return null;
        }
        return UserItemBo.buildByPo(xiuxianUserItemPO);

    }

    //卸下身上的装备
    public String removeEqip(UserBO user,XiuxianUserEquip myEquip,QualityEnum qualityEnum) {
        try {
            //删除穿戴的装备
            xiuxianUserEquipMapper.deleteById(myEquip.getId());
            //向背包中增加装备

            ItemInterface itemInterface = CommonEngine.ITEM_MAP.get(myEquip.getItemName());

            UserItemBo myItem = getMyItemForAddEquip(user.getId(), itemInterface.getName(),qualityEnum.getId());
            if (myItem != null) {
                myItem.setItemNum(myItem.getItemNum() + 1);
                xiuxianUserItemMapper.updateById(myItem);
            } else {
                UserItemBo item = new UserItemBo();
                item.setItemNum(1);
                item.setItemName(itemInterface.getName());
                item.setAccountId(user.getId());
                item.setItemAttr(itemInterface.attr(qualityEnum));
                item.setItemDesc(itemInterface.desc());
                item.setItemType(itemInterface.getType().getId());
                item.setItemPrice(itemInterface.getPrice());
                xiuxianUserItemMapper.insert(item);
            }
            return MessageFormat.format("已成功卸下[{0}] {1}",qualityEnum.getName(),myEquip.getItemName());
        }catch (Exception e){
            return "失败了QAQ";
        }

    }

    //按品质和名称查找穿戴的装备
    public XiuxianUserEquip getMyEqipWear(Long id, String itemName, int quality) {
        List<XiuxianUserEquip> xiuxianUserEquips = xiuxianUserEquipMapper.selectList(new LambdaQueryWrapper<XiuxianUserEquip>()
                .eq(XiuxianUserEquip::getAccountId, id)
                .eq(XiuxianUserEquip::getItemName, itemName));
        if (xiuxianUserEquips.size() == 0) {
            return null;
        }
        XiuxianUserEquip xiuxianUserItemPO = xiuxianUserEquips.stream().filter(i -> JSONUtil.toBean(i.getItemAttr(), ItemAttr.class).getQuality() == quality).findFirst().orElse(null);
        return xiuxianUserItemPO;

    }

    public XiuXianDrawing getEqipDraw(String name) {
        List<XiuXianDrawing> drawings = xiuxianDrawingMapper.selectList(new LambdaQueryWrapper<XiuXianDrawing>().eq(XiuXianDrawing::getEquipName, name));
        if(drawings.size() == 0){
            return null;
        }
        return drawings.get(0);
    }

    public List<XiuXianDrawing> getAlchemy(String name) {
        List<XiuXianDrawing> drawings = xiuxianDrawingMapper.selectList(new LambdaQueryWrapper<XiuXianDrawing>().eq(XiuXianDrawing::getEquipName, name).eq(XiuXianDrawing::getType,101));
        return drawings;
    }

    @Transactional
    public Boolean forgeEquipCheck(UserBO user, HashMap<String, Integer> hashMap) {
        Set<String> strings = hashMap.keySet();
        for (String s : strings){
            UserItemBo myItem = getMyItem(user.getId(), s);
            if(myItem == null || myItem.getItemNum() < hashMap.get(s)){
                throw new HandlerException(MessageFormat.format("你缺少相应的素材：[{0}]*{1}",s,hashMap.get(s)));
            }else {
                myItem.setItemNum(myItem.getItemNum() - hashMap.get(s));
                xiuxianUserItemMapper.updateById(myItem);
            }
        }
        return true;
    }

    public List<XiuXianDrawing> getAllDrawing(Integer num) {
        return xiuxianDrawingMapper.selectList(new LambdaQueryWrapper<XiuXianDrawing>().lt(XiuXianDrawing::getType,num));
    }

    public void addShopItem(XiuxianShopItem item) {
        xiuxianShopItemMapper.insert(item);
    }

    public List<XiuXianDrawing> getAllAlchemy() {
        return xiuxianDrawingMapper.selectList(new LambdaQueryWrapper<XiuXianDrawing>().eq(XiuXianDrawing::getType,101));
    }

    @Transactional
    public Boolean checkAlchemy(UserBO user, String perName, List<XiuXianDrawing> alchemy, ItemInterface itemInterface) {
        if(user.getUserConfig().getGold() < itemInterface.getPrice()/10){
            throw new HandlerException("你没有足够的摩拉，本次锻造需要耗费："+itemInterface.getPrice()/10);
        }
        if(alchemy.size() == 0){
            throw new HandlerException("这种物品无法合成");
        }
        XiuXianDrawing choose = new XiuXianDrawing();
        if(perName != null){
            for (XiuXianDrawing draw : alchemy){
                HashMap<String,Integer> hashMap = JSONUtil.toBean(draw.getSucaiDesc(), HashMap.class);
                Set<String> strings = hashMap.keySet();
                for (String s : strings) {
                    if (perName.equals(s)){
                        choose = draw;
                        break;
                    }
                }
            }
            if(choose.getSucaiDesc() == null){
                choose = alchemy.get(0);
            }
        }else {
            choose = alchemy.get(0);
        }

        HashMap<String,Integer> hashMap = JSONUtil.toBean(choose.getSucaiDesc(), HashMap.class);
        Set<String> strings = hashMap.keySet();
        for (String s : strings){
            UserItemBo myItem = getMyItem(user.getId(), s);
            if(myItem == null || myItem.getItemNum() < hashMap.get(s)){
                throw new HandlerException(MessageFormat.format("你缺少相应的素材：[{0}]*{1}",s,hashMap.get(s)));
            }else {
                myItem.setItemNum(myItem.getItemNum() - hashMap.get(s));
                xiuxianUserItemMapper.updateById(myItem);
            }
        }
        return true;

    }

    @Transactional
    public String addMineral(List<WeightRandom.WeightObj<String>> list, Map<String, Integer> map, UserBO userBO) {
        WeightRandom<String> stringWeightRandom = RandomUtil.weightRandom(list);
        String itemName = stringWeightRandom.next();
        Integer num = map.get(itemName);
        Integer stage = userBO.getStage()/2;
        num = RandomUtil.randomInt(num+stage) + 1;
        ItemInterface itemInterface = CommonEngine.ITEM_MAP.get(itemName);
        addItem(userBO,itemInterface,num);
        return new StringBuffer().append(itemName).append("*").append(num).toString();
    }


    @Transactional
    public boolean checkStrength(UserBO user, UserItemBo myEqip) {
        ItemAttr itemAttr = JSONUtil.toBean(myEqip.getItemAttr(), ItemAttr.class);
        ArrayList<String> mineralList = Lists.newArrayList("玄铁矿", "白铁矿", "水晶矿", "魔晶矿", "紫晶矿");
        Integer quality = itemAttr.getQuality();
        String s = mineralList.get(quality - 1);

        Map<String,Integer> hashMap = new HashMap<>();
        hashMap.put("无色晶体",quality*4);
        hashMap.put("萃凝晶",20);
        hashMap.put(s,20);
        Set<String> strings = hashMap.keySet();

        for (String a : strings){
            UserItemBo myItem = getMyItem(user.getId(), a);
            if(myItem == null || myItem.getItemNum() < hashMap.get(a)){
                throw new HandlerException(MessageFormat.format("你缺少相应的素材：[{0}]*{1}",a,hashMap.get(a)));
            }else {
                myItem.setItemNum(myItem.getItemNum() - hashMap.get(a));
                xiuxianUserItemMapper.updateById(myItem);
            }
        }
        return true;

    }
}
